package com.yunchao.bank.configure.presentation.screen

import com.yunchao.bank.configure.domain.model.ConfigureModel
import com.yunchao.bank.configure.domain.repository.ConfigureRepository
import com.yunchao.feature.base.domain.result.errorMsg
import com.yunchao.feature.base.presentation.viewmodel.BaseAction
import com.yunchao.feature.base.presentation.viewmodel.BaseEffect
import com.yunchao.feature.base.presentation.viewmodel.BaseState
import com.yunchao.feature.base.presentation.viewmodel.BaseViewModel

internal class ConfigureViewModel(private val repository: ConfigureRepository) :
    BaseViewModel<ConfigureViewModel.UiState, ConfigureViewModel.Action, ConfigureViewModel.UiEffect>(
        UiState.Idle
    ) {

    init {
        getConfigure()
    }

    fun saveConfigure(configure: ConfigureModel) = safeLaunch(
        onStart = { postSideEffect(UiEffect.ShowLoading) },
        onFinally = { postSideEffect(UiEffect.HideLoading) },
        onError = { postSideEffect(UiEffect.ShowToast(it.errorMsg)) },
    ) {
        val result = repository.saveConfigure(configure).getOrThrow()
        if (result) postSideEffect(UiEffect.NavigateToMain) else postSideEffect(
            UiEffect.ShowToast(
                "保存失败"
            )
        )
    }

    private fun getConfigure() = safeLaunch(
        onStart = { postSideEffect(UiEffect.ShowLoading) },
        onFinally = { postSideEffect(UiEffect.HideLoading) },
        onError = { postSideEffect(UiEffect.ShowToast(it.errorMsg)) }
    ) {
        val result = repository.getConfigure().getOrThrow()
        sendAction(Action.LoadConfigureSuccess(result))
    }

    internal sealed interface UiEffect : BaseEffect {
        data object ShowLoading : UiEffect
        data object HideLoading : UiEffect
        data class ShowToast(val msg: String) : UiEffect
        data object NavigateToMain : UiEffect
    }

    internal sealed interface UiState : BaseState {
        data object Idle : UiState
        data class Success(val configure: ConfigureModel) : UiState
    }

    internal sealed interface Action : BaseAction<UiState> {
        class LoadConfigureSuccess(val configure: ConfigureModel) : Action {
            override fun reduce(state: UiState) = UiState.Success(configure)
        }
    }
}